package indy.test.indy;

import indy.test.BlackBoxFileTransformer;
import indy.test.BlackBoxTest;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Handle;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import static org.objectweb.asm.Opcodes.*;

@BlackBoxTest
public class BSMFalseSharing implements BlackBoxFileTransformer {
    static final Handle BSM1 = new Handle(H_INVOKESTATIC, BSMFalseSharingTemplate.class.getName().replace('.', '/'), "bsm1",
            "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;");
    static final Handle BSM2 = new Handle(H_INVOKESTATIC, BSMFalseSharingTemplate.class.getName().replace('.', '/'), "bsm2",
            "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;)Ljava/lang/invoke/CallSite;");
    
    
    @Override
    public ClassVisitor transform(ClassVisitor cv) {
        return new ClassVisitor(Opcodes.ASM4, cv) {
            @Override
            public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
                final String methodName = name;
                MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
                if (!methodName.equals("main")) {
                    return mv;
                }
                
                return new MethodVisitor(Opcodes.ASM4, mv) {
                    @Override
                    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
                        Handle handle;
                        Object arg;
                        if (name.charAt(name.length() -1) == '1') {
                            handle = BSM1;
                            arg = 143;
                        } else {
                            handle = BSM2;
                            arg = "zzz";
                        }
                        super.visitInvokeDynamicInsn(name, desc, handle, arg);
                    }
                };
            }
        };
    }
}
